package it.polimi.traveldream.managers;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceException;
import javax.annotation.Resource;
//import javax.annotation.security.RolesAllowed;
//import javax.ejb.EJB;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;
//import javax.persistence.EntityManager;
//import javax.persistence.PersistenceContext;

//import org.apache.commons.codec.digest.DigestUtils;


import it.polimi.traveldream.managers.credentials.UserCredentialManager.UserAlreadyExistsException;
import it.polimi.traveldream.persistence.Aeroporto;
import it.polimi.traveldream.persistence.Compagnia;
import it.polimi.traveldream.persistence.GiftListHotel;
import it.polimi.traveldream.persistence.GiftListTour;
import it.polimi.traveldream.persistence.GiftListVolo;
import it.polimi.traveldream.persistence.GruppoUtente;
import it.polimi.traveldream.persistence.Hotel;
import it.polimi.traveldream.persistence.Localita;
import it.polimi.traveldream.persistence.Pacchetto;
import it.polimi.traveldream.persistence.PacchettoPersonalizzato;
import it.polimi.traveldream.persistence.PrenotazioneHotel;
import it.polimi.traveldream.persistence.PrenotazioneTour;
import it.polimi.traveldream.persistence.PrenotazioneVolo;
import it.polimi.traveldream.persistence.Tour;
import it.polimi.traveldream.persistence.TrattaVolo;
import it.polimi.traveldream.persistence.Utente;
import it.polimi.traveldream.persistence.dtos.AeroportoDTO;
import it.polimi.traveldream.persistence.dtos.CompagniaDTO;
import it.polimi.traveldream.persistence.dtos.GiftListHotelDTO;
import it.polimi.traveldream.persistence.dtos.GiftListTourDTO;
import it.polimi.traveldream.persistence.dtos.GiftListVoloDTO;
import it.polimi.traveldream.persistence.dtos.HotelProdDTO;
import it.polimi.traveldream.persistence.dtos.LocalitàDTO;
import it.polimi.traveldream.persistence.dtos.PacchettoDTO;
import it.polimi.traveldream.persistence.dtos.PacchettoPersonalizzatoDTO;
import it.polimi.traveldream.persistence.dtos.PrenotazioneHotelDTO;
import it.polimi.traveldream.persistence.dtos.PrenotazioneTourDTO;
import it.polimi.traveldream.persistence.dtos.PrenotazioneVoloDTO;
import it.polimi.traveldream.persistence.dtos.TourProdDTO;
import it.polimi.traveldream.persistence.dtos.TrattaProdDTO;
import it.polimi.traveldream.persistence.dtos.UserDTO;

@Stateless
public class CarrelloManagerImpl implements CarrelloManager {
	
	@EJB(beanName="ProductManagerImpl")
	private ProductManager productMgr;
	

	@EJB(beanName="PacchettoPersonalizzatoManagerImpl")
	private PacchettoPersonalizzatoManager persPackMgr;
	
	@Resource
	private EJBContext context;
	
	@PersistenceContext
	private EntityManager em;
	
	
	private ProductManagerImpl getProductManager() {
		return (ProductManagerImpl) productMgr;
	}
	
	private PacchettoPersonalizzatoManagerImpl getPacchettoPersonalizzato() {
		return (PacchettoPersonalizzatoManagerImpl) persPackMgr;
	}
	
	@Override
	public void salvaInCarrello(PacchettoPersonalizzatoDTO pacchetto) throws DataBaseException {
		try {
		//devo convertire il pacchetto e tutte le variabili associate ad esso da DTO a entity
		PacchettoPersonalizzato newPacchetto= convertiPacchettoPersonalizzato(pacchetto);	
		//PacchettoPersonalizzato newPacchetto=
		//newPacchetto.setIDPacchettoPers(pacchetto.getIDPacchetto());
		String utente= context.getCallerPrincipal().getName();
		Utente u= em.find(Utente.class, utente);
		if(em.find(Utente.class, utente)!=null){
			
				newPacchetto.setUtente(em.find(Utente.class, utente));
				em.persist(newPacchetto);
		}
		} catch (Exception e) {
			throw new DataBaseException(e);
		}
	}
	
	public void modificaCarrello(PacchettoPersonalizzatoDTO pacchetto, int prenotazione) throws UserAlreadyExistsException{
		PacchettoPersonalizzato newPacchetto= convertiPacchettoPersonalizzato(pacchetto);	
		//newPacchetto.setPrenotazione((byte)1);
		PacchettoPersonalizzato updP= em.find(PacchettoPersonalizzato.class, pacchetto.getIDPacchetto());
		updatePacchettoPersonalizzato(updP,prenotazione,pacchetto);
		String utente= context.getCallerPrincipal().getName();
		Utente u= em.find(Utente.class, utente);
		if(em.find(Utente.class, utente)!=null){
				em.merge(updP);
				newPacchetto= em.find(PacchettoPersonalizzato.class, pacchetto.getIDPacchetto());
		}
	}
	
	public void updatePacchettoPersonalizzato(PacchettoPersonalizzato pack, int prenotazione, PacchettoPersonalizzatoDTO packDTO){
		pack.setPrenotazione((byte)prenotazione);
		for (PrenotazioneHotelDTO  hotelDTO: packDTO.getHotels()) {
			PrenotazioneHotel hotel= em.find(PrenotazioneHotel.class, hotelDTO.getIDPrenotazione());
			if(hotel==null){
				hotel=new PrenotazioneHotel();
				convertPrenotazioneHotel(hotelDTO, hotel);
				pack.addPrenotazioneHotels1(hotel);
			}
			else{
				convertPrenotazioneHotel(hotelDTO, hotel);
			}
			
		}
		for(PrenotazioneTourDTO tourDTO: packDTO.getTours()){
			PrenotazioneTour tour= em.find(PrenotazioneTour.class, tourDTO.getIDPrenotazione());
			if(tour==null){
				tour= new PrenotazioneTour();
				convertPrenotazioneTour(tourDTO, tour);
				pack.addPrenotazioneTours1(tour);
			}
			else{
				convertPrenotazioneTour(tourDTO, tour);
			}
		}
		
		for(PrenotazioneVoloDTO voloDTO: packDTO.getVoli()){
			PrenotazioneVolo volo= em.find(PrenotazioneVolo.class, voloDTO.getIdPrenotazione());
			if(volo==null){
				volo= new PrenotazioneVolo();
				convertPrenotazioneVoli(voloDTO, volo);
				pack.addPrenotazioneVolos1(volo);
			}
			else{
				convertPrenotazioneVoli(voloDTO, volo);
			}
		}
	}
	
	public List<PacchettoPersonalizzatoDTO> findAllPackWithGift(UserDTO user){
		List<PacchettoPersonalizzatoDTO> paccDTO= new ArrayList<PacchettoPersonalizzatoDTO>();
		boolean controllo=false;
		List<PacchettoPersonalizzato> pack= em.createNamedQuery(PacchettoPersonalizzato.FIND_BY_UTENTE, PacchettoPersonalizzato.class).setParameter("utente", user.getEmail()).setParameter("prenotazione", 0).getResultList();
		for (PacchettoPersonalizzato pp : pack) {
			List<PrenotazioneHotelDTO> prenHotel= new ArrayList<PrenotazioneHotelDTO>();
			List<PrenotazioneVoloDTO> prenVolo= new ArrayList<PrenotazioneVoloDTO>();
			List<PrenotazioneTourDTO> prenTour= new ArrayList<PrenotazioneTourDTO>();
			controllo=false;
			List<GiftListHotel> giftHotel= em.createNamedQuery("GiftListHotel.findPacchetto", GiftListHotel.class).setParameter("id", pp.getIDPacchettoPers()).getResultList();
			for(GiftListHotel g : giftHotel){
				PrenotazioneHotelDTO hotel= new PrenotazioneHotelDTO();
				hotel=convertPrenotazioneHotelDTO(g.getPrenotazioneHotel());
				prenHotel.add(hotel);
				controllo=true;
			}
			List<GiftListVolo> giftVolo= em.createNamedQuery("GiftListHotel.findPacchettoVolo", GiftListVolo.class).setParameter("id", pp.getIDPacchettoPers()).getResultList();
			for(GiftListVolo g : giftVolo){
				PrenotazioneVoloDTO volo= new PrenotazioneVoloDTO();
				volo=convertPrenotazioneVoliDTO(g.getPrenotazioneVolo());
				controllo=true;
			}
			List<GiftListTour> giftTour= em.createNamedQuery("GiftListTour.findPacchettoTour", GiftListTour.class).setParameter("id", pp.getIDPacchettoPers()).getResultList();

			for(GiftListTour t : giftTour){
				PrenotazioneTourDTO tour= new PrenotazioneTourDTO();
				tour= convertPrenotazioneTourDTO(t.getPrenotazioneTour());
				prenTour.add(tour);
				controllo=true;
			}
			if(controllo){
				PacchettoPersonalizzatoDTO pDTO= new PacchettoPersonalizzatoDTO();
				pDTO= convertiPacchettoPersonalizzatoDTO(pp);
				pDTO.setHotelsInGL(prenHotel);
				pDTO.setVoliInGL(prenVolo);
				pDTO.setToursInGL(prenTour);
				paccDTO.add(pDTO);
			}
		}
		return paccDTO;
		
		
		//List<PacchettoPersonalizzato> pack= em.createNamedQuery(PacchettoPersonalizzato.FIND_GIFT_HOTEL,PacchettoPersonalizzato.class).setParameter("utente", user.getEmail()).getResultList();
		/*for (PacchettoPersonalizzato pp : pack) {
			for (PacchettoPersonalizzatoDTO ppDTO : pDTO) {
				if(ppDTO.getIDPacchetto()==pp.getIDPacchettoPers()){
					controllo=true;
				}
			}
			if(controllo){
				controllo=false;
			}else{
				pDTO.add(convertiPacchettoPersonalizzatoDTO(pp));
			}
		}
		
		return pDTO;*/
	}
	
	public List<PacchettoPersonalizzatoDTO> findAllAggiuntiInCarrello(int prenotazione){
		List<PacchettoPersonalizzatoDTO> pacchettoDTO= new ArrayList<PacchettoPersonalizzatoDTO>();
		String utente= context.getCallerPrincipal().getName();
		List<PacchettoPersonalizzato> pacchetto= em.createNamedQuery(PacchettoPersonalizzato.FIND_BY_UTENTE, PacchettoPersonalizzato.class).setParameter("utente",utente).setParameter("prenotazione", prenotazione).getResultList();
		for(PacchettoPersonalizzato p: pacchetto){
			//PacchettoPersonalizzatoDTO pDTO= getPacchettoPersonalizzato().convert(p);
			PacchettoPersonalizzatoDTO pDTO= convertiPacchettoPersonalizzatoDTO(p);
			if(pDTO!=null){
					pacchettoDTO.add(pDTO);
			}
		}
		return pacchettoDTO;
	}
	
	public PacchettoPersonalizzato convertiPacchettoPersonalizzato(PacchettoPersonalizzatoDTO packDTO){
		PacchettoPersonalizzato pack= new PacchettoPersonalizzato();
		List<PrenotazioneHotel> hotels= new ArrayList<PrenotazioneHotel>();
		List<PrenotazioneTour> tours= new ArrayList<PrenotazioneTour>();
		List<PrenotazioneVolo> voli= new ArrayList<PrenotazioneVolo>();
		byte b=0;
		pack.setPrenotazione((byte)0);
		pack.setPacchetto(em.find(Pacchetto.class, packDTO.getIDPacchettoOriginale()));
		
		//pack.setIDPacchettoPers(packDTO.getIDPacchettoOriginale());
		if (packDTO.getHotels()!=null){
			for(PrenotazioneHotelDTO prenhoteldto : packDTO.getHotels() ){
					PrenotazioneHotel hotel= new PrenotazioneHotel();
					convertPrenotazioneHotel(prenhoteldto,hotel);
					hotel.setPacchettoPersonalizzato(pack);
					hotels.add(hotel);
			}
		}else{
			hotels=null;
		}
		
		if(packDTO.getTours()!=null){
			for(PrenotazioneTourDTO prenTourDTO : packDTO.getTours()){
				PrenotazioneTour tour= new PrenotazioneTour();
				convertPrenotazioneTour(prenTourDTO,tour);
				tour.setPacchettoPersonalizzato(pack);
				tours.add(tour);
			}
		}else{
			tours=null;
		}
		if(packDTO.getVoli()!=null){
			for(PrenotazioneVoloDTO prenVoloDTO : packDTO.getVoli()){
				PrenotazioneVolo volo= new PrenotazioneVolo();
				 convertPrenotazioneVoli(prenVoloDTO, volo);
				volo.setPacchettoPersonalizzato(pack);
				voli.add(volo);
			}
		}else{
			voli=null;
		}
		pack.setPrenotazioneHotels1(hotels);
		pack.setPrenotazioneTours1(tours);
		pack.setPrenotazioneVolos1(voli);
		return pack;
	}
	
	public PacchettoPersonalizzatoDTO convertiPacchettoPersonalizzatoDTO(PacchettoPersonalizzato packEntity){
		if (packEntity!=null){
			PacchettoPersonalizzatoDTO pack= new PacchettoPersonalizzatoDTO();
			List<PrenotazioneHotelDTO> hotels= new ArrayList<PrenotazioneHotelDTO>();
			List<PrenotazioneTourDTO> tours= new ArrayList<PrenotazioneTourDTO>();
			List<PrenotazioneVoloDTO> voli= new ArrayList<PrenotazioneVoloDTO>();
			pack.setPrenotazione(packEntity.getPrenotazione());
			pack.setIDPacchetto(packEntity.getIDPacchettoPers());
			//pack.setPacchetto(em.find(Pacchetto.class, packDTO.getIDPacchettoOriginale()));
			pack.setIDPacchettoOriginale(packEntity.getPacchetto().getID());
			pack.setPacchettoOriginale(convertDTO(packEntity.getPacchetto()));
			for(PrenotazioneHotel prenhotel : packEntity.getPrenotazioneHotels1() ){
				PrenotazioneHotelDTO h= convertPrenotazioneHotelDTO(prenhotel);
				hotels.add(h);
			}
			
			for(PrenotazioneTour prenTour : packEntity.getPrenotazioneTours1()){
				PrenotazioneTourDTO t= convertPrenotazioneTourDTO(prenTour);
				tours.add(t);
			}
			
			for(PrenotazioneVolo prenVolo : packEntity.getPrenotazioneVolos1()){
				PrenotazioneVoloDTO v = convertPrenotazioneVoliDTO(prenVolo);
				voli.add(v);
			}
			pack.setHotels(hotels);
			pack.setTours(tours);
			pack.setVoli(voli);
			return pack;
		}else{
			return null;
		}
	}
	
	public PacchettoDTO convertDTO(Pacchetto pacchetto) {
		if(pacchetto!=null){
			PacchettoDTO pacchettoDTO = new PacchettoDTO();
			pacchettoDTO.setDescrizione(pacchetto.getDescrizione());
			pacchettoDTO.setEmailImpiegato(pacchetto.getUtente().getEmail());
			pacchettoDTO.setIDPacchetto(pacchetto.getID());
			pacchettoDTO.setNome(pacchetto.getNome());
			pacchettoDTO.setPubblico(pacchetto.getPubblico());
			return pacchettoDTO;
		}
		else{
			return null;
		}
	}
	
	public void convertPrenotazioneHotel(PrenotazioneHotelDTO hotelDTO, PrenotazioneHotel hotel){
		//PrenotazioneHotel hotel= new PrenotazioneHotel();
		hotel.setCheckin(hotelDTO.getCheckIN());
		hotel.setCheckout(hotelDTO.getCheckOUT());
		hotel.setNumeroPersone(hotelDTO.getNumeroPersone());
		hotel.setHotel(em.find(Hotel.class, hotelDTO.getHotel().getID()));
		//return hotel;
	}
	
	public PrenotazioneHotelDTO convertPrenotazioneHotelDTO(PrenotazioneHotel hotel){
		if(hotel!=null){
			PrenotazioneHotelDTO hotelDTO= new PrenotazioneHotelDTO();
			hotelDTO.setCheckOUT(hotel.getCheckout());
			hotelDTO.setCheckIN(hotel.getCheckin());
			hotelDTO.setIDPrenotazione(hotel.getIDPrenotazione());
			hotelDTO.setNumeroPersone(hotel.getNumeroPersone());
			hotelDTO.setHotel(convertiHotel(hotel.getHotel()));
			if(hotel.getGiftListHotels()!=null){
				hotelDTO.setGiftList(convertGiftListHotelDTO(hotel.getGiftListHotels()));
			}
			return hotelDTO;
		}else{
			return null;
		}
	}
	
	public GiftListHotelDTO convertGiftListHotelDTO(GiftListHotel gift){
		GiftListHotelDTO giftDTO= new GiftListHotelDTO();
		giftDTO.setIDPacchetto(gift.getPacchettoPersonalizzato().getIDPacchettoPers());
		giftDTO.setIDPrenotazioneHotel(gift.getPrenotazioneHotel().getIDPrenotazione());
		if(gift.getUtente()!=null){
			giftDTO.setPagante(convertUtente(gift.getUtente()));
		}
		return giftDTO;
	}
	
	public UserDTO convertUtente(Utente user) {
		UserDTO userDTO = new UserDTO();
		userDTO.setEmail(user.getEmail());
		userDTO.setFirstName(user.getNome());
		userDTO.setLastName(user.getCognome());
		userDTO.setIsClient(user.getGruppoUtente().contains(
				GruppoUtente.CLIENTE));
		return userDTO;
	}
	
	public void convertPrenotazioneTour(PrenotazioneTourDTO tourDTO, PrenotazioneTour tour){
		
		tour.setNumeroPersone(tourDTO.getNumeroPersone());
		tour.setData(tourDTO.getData());
		tour.setTour(em.find(Tour.class,tourDTO.getTour().getID()));
		//return tour;
	}
	
	public PrenotazioneTourDTO convertPrenotazioneTourDTO(PrenotazioneTour tourEntity){
		if(tourEntity!=null){
			PrenotazioneTourDTO tour= new PrenotazioneTourDTO();
			tour.setIDPrenotazione(tourEntity.getIDPrenotazione());
			tour.setNumeroPersone(tourEntity.getNumeroPersone());
			tour.setData(tourEntity.getData());
			tour.setTour(convertTourDTO(tourEntity.getTour()));
			if(tourEntity.getGiftListTours()!=null){
				tour.setGiftList(convertGiftListTourDTO(tourEntity.getGiftListTours()));
			}
			return tour;
		}else{
			return null;
		}
	}
	

	public GiftListTourDTO convertGiftListTourDTO(GiftListTour gift){
		GiftListTourDTO giftDTO= new GiftListTourDTO();
		giftDTO.setIDPacchetto(gift.getPacchettoPersonalizzato().getIDPacchettoPers());
		giftDTO.setIDPrenotazioneHotel(gift.getPrenotazioneTour().getIDPrenotazione());
		if(gift.getUtente()!=null){
			giftDTO.setPagante(convertUtente(gift.getUtente()));
		}
		return giftDTO;
	}
	
	public void convertPrenotazioneVoli(PrenotazioneVoloDTO voloDTO, PrenotazioneVolo volo){
		
		volo.setData(voloDTO.getData());
		volo.setNumeroPersone(voloDTO.getNumeroPersone());
		volo.setTrattaVolo(em.find(TrattaVolo.class, voloDTO.getTrattaVolo().getID()));
		//return volo;
	}
	
	public PrenotazioneVoloDTO convertPrenotazioneVoliDTO(PrenotazioneVolo voloEntity){
		PrenotazioneVoloDTO volo= new PrenotazioneVoloDTO();
		if(voloEntity!=null){
			volo.setIdPrenotazione(voloEntity.getIDPrenotazione());
			volo.setData(voloEntity.getData());
			volo.setNumeroPersone(voloEntity.getNumeroPersone());
			volo.setTrattaVolo(convertTrattaDTO(voloEntity.getTrattaVolo()));
			if(voloEntity.getGiftListVolos()!=null){
				volo.setGiftList(convertGiftListVoloDTO(voloEntity.getGiftListVolos()));
			}
		}
		return volo;
	}
	
	public GiftListVoloDTO convertGiftListVoloDTO(GiftListVolo gift){
		GiftListVoloDTO giftDTO= new GiftListVoloDTO();
		giftDTO.setIDPacchetto(gift.getPacchettoPersonalizzato().getIDPacchettoPers());
		giftDTO.setIDPrenotazioneHotel(gift.getPrenotazioneVolo().getIDPrenotazione());
		if(gift.getUtente()!=null){
			giftDTO.setPagante(convertUtente(gift.getUtente()));
		}
		return giftDTO;
	}
	
	public TrattaProdDTO convertTrattaDTO(TrattaVolo pTratta) {
		TrattaProdDTO trattaDTO = new TrattaProdDTO();
		if(pTratta!=null){
			trattaDTO.setEmailImpiegato(pTratta.getUtente().getEmail());
			trattaDTO.setCompagnia(convertCompagnia(pTratta.getCompagnia()));
			trattaDTO.setaAeroporto(convertAeroporto(pTratta.getAdAeroporto()));
			trattaDTO.setDaAeroporto(convertAeroporto(pTratta.getDaAeroporto()));
			trattaDTO.setID(pTratta.getIDTratta());
			
		}
		return trattaDTO;
	}

	public CompagniaDTO convertCompagnia(Compagnia compagnia) {
		CompagniaDTO compagniaDTO = new CompagniaDTO();
		if(compagnia!=null){
			
			compagniaDTO.setNome(compagnia.getNome());
			compagniaDTO.setID(compagnia.getIDCompagnia());
			
		}
		return compagniaDTO;
	}
	
	public AeroportoDTO convertAeroporto(Aeroporto aeroporto) {
		AeroportoDTO aeroportoDTO = new AeroportoDTO();
		if(aeroporto!=null){
		
		aeroportoDTO.setID(aeroporto.getIDAeroporto());
		aeroportoDTO.setIDlocalità(aeroporto.getLocalita().getIDLocalita());
		aeroportoDTO.setLocalita(convertiLocalita(aeroporto.getLocalita()));
		aeroportoDTO.setName(aeroporto.getNome());
		
		}
		return aeroportoDTO;
	}
	
	public HotelProdDTO convertiHotel(Hotel hotel){
		HotelProdDTO hotelDTO= new HotelProdDTO();
		if(hotel!=null){
			hotelDTO.setID(hotel.getIDHotel());
			hotelDTO.setEmailImpiegato(hotel.getUtente().getEmail());
			hotelDTO.setLocalitàID(hotel.getLocalita().getIDLocalita());
			hotelDTO.setNome(hotel.getNome());
			hotelDTO.setNumeroCivico(hotel.getNumeroCivico());
			hotelDTO.setVia(hotel.getVia());
			hotelDTO.setLocalita(convertiLocalita(hotel.getLocalita()));
			return hotelDTO;
		}
		return hotelDTO;
	}
	
	public LocalitàDTO convertiLocalita(Localita loc){
		LocalitàDTO locDTO= new LocalitàDTO();
		if(loc!=null){
			locDTO.setID(loc.getIDLocalita());
			locDTO.setNome(loc.getNome());
			locDTO.setDescrizione(loc.getDescrizione());
			locDTO.setStato(loc.getStato());
			locDTO.setProvincia(loc.getProvincia());
			return locDTO;
		}
		return locDTO;
	}
	
	public TourProdDTO convertTourDTO(Tour tour){
		TourProdDTO tourDTO= new TourProdDTO();
		if(tour!=null){			
			tourDTO.setDescrizione(tour.getDescrizione());
			tourDTO.setEmailImpiegato(tour.getUtente().getEmail());
			tourDTO.setID(tour.getIDTour());
			tourDTO.setLocalita(convertiLocalita(tour.getLocalita()));
		}return tourDTO;
	}
}


